/*
 * Copyright (C) 2006 Roman Krashanitsa
 *
 * @author Roman Krashanitsa
 *
 * This file is part of paparazzi.
 *
 * paparazzi is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * paparazzi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with paparazzi; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA. 
 *
 */

package pprz.components;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.JScrollPane;
import javax.swing.event.EventListenerList;

import pprz.data_components.Aircraft;
import pprz.data_components.Message;
import pprz.data_components.events.DownlinkMessageEvent;
import pprz.data_components.events.DownlinkMessageEventListener;


public class AcInfoPanel extends JScrollPane implements DownlinkMessageEventListener  {

	protected static final long serialVersionUID = 1L;
//	protected Link link;
	protected HashMap<Integer,Aircraft> acInfo=null;  //there is only one  //  @jve:decl-index=0:
	
	protected AcInfo panel;

	public static final int colors[]={0x111111, 0x111188, 0x1111FF, 0x118811,
		0x11FF11, 0x881111, 0xFF1111, 0xFF1188,
		0x881188, 0x8811FF, 0xFF11FF, 0x118888,
		0x11FFFF, 0x1188FF, 0x11FF88};
	
	class AcInfo extends Component implements MouseListener{

		protected static final long serialVersionUID = 2L;

		HashMap<Integer,Aircraft> acInfo;
//		protected Link link=null;
		protected HashMap<Integer,Integer> order=null;
		protected Vector<Integer> order_list=null;
		
		protected Image dbImage;  //  @jve:decl-index=0:
		protected int size_x;
		protected int size_y;
		protected int selected;

		protected int textWidth;
		protected int numbersWidth;
		protected int lineHeight;
		protected int marginX, marginY;		
		
		protected EventListenerList listenerList = new EventListenerList();  //  @jve:decl-index=0:
		protected ActionEvent e;
 

		
		public AcInfo(HashMap<Integer,Aircraft> acInfo) {
			super();
			assert acInfo==null; 
			this.acInfo=acInfo;
			
			size_x=73; size_y=86;
			textWidth=33; numbersWidth=40;
			lineHeight=15;
			marginX=1; marginY=2;
			
			selected=0;
//			mousePressed=false;
			e=new ActionEvent(this,0,null);
			this.addMouseListener(this);
			order=new HashMap<Integer,Integer>();
			order_list=new Vector<Integer>();
			setMinimumSize(new Dimension(10,10));
		}
		
		public void add(Aircraft a)
		{
			if (order_list.size()==0) selected=a.get_id();
			order.put(a.get_id(), order.size());
			order_list.add(a.get_id());
			if (dbImage!=null) dbImage.flush();
			dbImage = createImage (this.getWidth(), this.getHeight());
			if (dbImage!=null)
			{
				Graphics g=dbImage.getGraphics();
				Graphics2D g2=(Graphics2D)g;
				if (order_list.size()==1)
				{
					FontMetrics fm=g2.getFontMetrics();
					textWidth=fm.stringWidth("Pitch: ");
					numbersWidth=fm.stringWidth("0000000")+3;
					lineHeight=fm.getHeight();
					marginX=Math.round(0.1f*textWidth)+5; 
					marginY=Math.round(0.1f*lineHeight)+5;
					size_x=textWidth+numbersWidth+marginX;
					size_y=5*lineHeight+marginY;				
				}
				draw(g2);
				this.getParent().repaint(100);					
			}
		}
		
		
		public void draw(Graphics g)
		{
//			System.out.println("AcInfoPanel.draw");
		//	if (acInfo==null) return;
			for (int i=0; i<order_list.size(); i++)
			{
				drawAc(g,acInfo.get(order_list.get(i)));
			}
			
		}
		
		public void drawAc(Graphics g, Aircraft ac){
			assert ac!=null;
			assert order!=null;
//			System.out.println("AcInfoPanel.drawAc");
			Graphics2D g2=(Graphics2D)g;
			int curY=marginY;
			Color c = new Color(ac.get_color());
			if (c==null) System.out.println(ac.get_color());
			curY=order.get(ac.get_id())*size_y;
			if (selected==ac.get_id()) g2.setColor(new Color(
					(c.getRed()+0xA0)>0xFF?0xFF:c.getRed()+0xA0,
					(c.getGreen()+0xA0)>0xFF?0xFF:c.getGreen()+0xA0,
					(c.getBlue()+0xA0)>0xFF?0xFF:c.getBlue()+0xA0
					));
			else g2.setColor(this.getBackground());
			g2.fillRect(0,curY,size_x,size_y);
		    g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
			g2.setColor(c);
			g2.fillRect(1,curY+1,5,size_y-1);
			String sID=String.valueOf(ac.get_id());
			String sAlt=String.valueOf(ac.get_gps_alt());
			String sVel=String.valueOf(ac.get_gps_vel());
			String sPitch=String.valueOf(ac.get_pitch());
			String sRoll=String.valueOf(ac.get_roll());
			curY+=lineHeight;
			g2.setColor(this.getForeground());
			g2.drawString("ID: ",marginX,curY); g2.drawString(sID,marginX+textWidth,curY); curY+=lineHeight;
			g2.drawString("Alt: ",marginX,curY); g2.drawString(sAlt,marginX+textWidth,curY); curY+=lineHeight;
			g2.drawString("Vel: ",marginX,curY); g2.drawString(sVel,marginX+textWidth,curY); curY+=lineHeight;
			g2.drawString("Pitch: ",marginX,curY); g2.drawString(sPitch,marginX+textWidth,curY); curY+=lineHeight;
			g2.drawString("Roll: ",marginX,curY); g2.drawString(sRoll,marginX+textWidth,curY); curY+=lineHeight;
		}
		
		public void repaint(Aircraft a)
		{
//			System.out.println("AcInfoPanel.repaint");
			Graphics dbg;
			if (dbImage!=null)
			{
				dbg = dbImage.getGraphics (); 
//			 	draw elements on the background image 
				drawAc(dbg,a);
//				repaint();
				repaint(50,textWidth+marginX,
						order.get(a.get_id())*size_y,
						size_x-numbersWidth,size_y);
				
			}
		}
		
		public void paint(Graphics g) {
//			System.out.println("AcInfoPanel.paint");
			g.drawImage (dbImage, 0, 0, this);
			 
		}
		
		public int getSelected()
		{return selected;}
		
		public void select(int id)
		{
//			if(acInfo==null) return;
			int old=selected;
			selected=id;
			fireActionEvent(this.e);
			if (dbImage!=null)
			{
				
				Graphics dbg = dbImage.getGraphics ();
				drawAc(dbg,acInfo.get(old));
				drawAc(dbg,acInfo.get(selected));
				dbg.dispose();				
				repaint(0,order.get(old)*size_y,size_x,size_y);				
				repaint(0,order.get(selected)*size_y,size_x,size_y);
			}
		}
		
		boolean exists(int acId)
		{
			return order.containsKey(acId);
		}
		
		

		@Override
		public Dimension getMinimumSize() {
			return new Dimension(size_x,size_y*order.size());
		}

		@Override
		public int getHeight() {
			return size_y*order.size();
		}

		@Override
		public Dimension getMaximumSize() {
			return new Dimension(size_x, size_y*order.size());
		}

		@Override
		public Dimension getPreferredSize() {
			return new Dimension(size_x, size_y*order.size());
		}

		@Override
		public Dimension getSize() {
			return new Dimension(size_x, size_y*order.size());
		}

		@Override
		public Dimension getSize(Dimension rv) {
			return new Dimension(size_x, size_y*order.size());
		}

		@Override
		public int getWidth() {
			return size_x;
		}

		public void mouseClicked(MouseEvent e) {}
		public void mouseEntered(MouseEvent e) {}
		public void mouseExited(MouseEvent e) {}
		public void mousePressed(MouseEvent e) {}

		public void mouseReleased(MouseEvent e) {
			if (e.getY()/size_y>=order_list.size() ||  e.getY()/size_y<0) return;
			else select(order_list.get(e.getY()/size_y));
		}
		
	    // These methods allows classes to register for MyEvents
	    public void addActionListener(ActionListener listener) {
	        listenerList.add(ActionListener.class, listener);
	    }

	    // This methods allows classes to unregister for MyEvents
	    public void removeActionListener(ActionListener listener) {
	        listenerList.remove(ActionListener.class, listener);
	    }
	    
	    // This protected class is used to fire MyEvents
	    protected void fireActionEvent(ActionEvent evt) {
	        Object[] listeners = listenerList.getListenerList();
	        // Each listener occupies two elements - the first is the listener class
	        // and the second is the listener instance
	        for (int i=0; i<listeners.length; i+=2) {
	            if (listeners[i]==ActionListener.class) {
	                ((ActionListener)listeners[i+1]).actionPerformed(evt);
	            }
	        }
	    }
	}

	public AcInfoPanel(HashMap<Integer,Aircraft> acInfo) {
		super();
		assert acInfo!=null;
		this.acInfo=acInfo;		
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	protected void initialize() {
		this.panel=new AcInfo(acInfo);
		panel.setBackground(this.getBackground());
		this.add(panel);
	}

	public void messageEvent(DownlinkMessageEvent ev) {
		Message m = ev.getMessage();
		int msgid=m.acRec().lastMSG;
		if (msgid!=6 && msgid!=8) return; //skip it
		if (!panel.exists(m.acRec().get_id())) panel.add(m.acRec());
		else panel.repaint(m.acRec());
	}

    // These methods allows classes to register for MyEvents
    public void addActionListener(ActionListener listener) {
        panel.addActionListener(listener);
    }

    // This methods allows classes to unregister for MyEvents
    public void removeActionListener(ActionListener listener) {
        panel.removeActionListener(listener);
    }	
	
} //class
